package com.spzx.common.log.aspect;

import com.spzx.common.log.annotation.Log;
import com.spzx.common.log.service.AsyncOperLogService;
import com.spzx.common.log.utils.LogUtil;
import com.spzx.model.entity.system.SysOperLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 环绕通知切面类定义
 * Project: spzx-parent
 * Package: com.spzx.common.log.aspect
 * Version: 1.0
 * <p>
 * Created by  wangjiaxin  on 2024/3/7 22:32
 */
@Aspect
@Component
@Slf4j
public class LogAspect {


    @Autowired
    private AsyncOperLogService asyncOperLogService;

    /**
     * 环绕AOP  测试代码
     *
     * @param joinPoint
     * @param sysLog
     * @return
     */
    /*@Around(value = "@annotation(sysLog)")
    public Object doAroundAdvice(ProceedingJoinPoint joinPoint, Log sysLog) {
        //获取注解的模块名称
        String title = sysLog.title();
        int businessType = sysLog.businessType();
        log.info("LogAspect...doAroundAdvice方法执行前通知了   title: " + title);
        log.info("LogAspect...doAroundAdvice方法执行前通知了   businessType: " + businessType);
//        System.out.println("LogAspect...doAroundAdvice方法执行了" + title);
        Object proceed = null;
        try {
            proceed = joinPoint.proceed();              // 执行业务方法

            log.info("在业务方法之后执行!!!!");
        } catch (Throwable e) {                         // 代码执行进入到catch中，业务方法执行产生异常
            throw new RuntimeException(e);
        }
        return proceed;                                // 返回执行结果
    }*/


    /**
     * @param joinPoint
     * @param sysLog
     * @return
     */
    /*
        AOP术语：
            1、切入点
            2、增强
                前面、后面、环绕、异常、返回
            3、切面
     */
    @Around(value = "@annotation(sysLog)")
    public Object doAroundAdvice(ProceedingJoinPoint joinPoint, Log sysLog) {

        // 构建前置参数
        SysOperLog sysOperLog = new SysOperLog();
        // 调用工具类，打印前后日志输出
        LogUtil.beforeHandleLog(sysLog, joinPoint, sysOperLog);

        Object proceed = null;
        try {
            proceed = joinPoint.proceed();
            // 执行业务方法
            LogUtil.afterHandlLog(sysLog, proceed, sysOperLog, 0, null);
            // 构建响应结果参数
        } catch (Throwable e) {                                 // 代码执行进入到catch中，
            // 业务方法执行产生异常
            e.printStackTrace();                                // 打印异常信息
            LogUtil.afterHandlLog(sysLog, proceed, sysOperLog, 1, e.getMessage());
            //TODO 由于没有手动设置优先级，spring中事务的切面优先级要高于日志的切面优先级，如果不抛出异常事务就感知不到异常，就不会进行回滚
            throw new RuntimeException();
        }

        // 保存日志数据
        asyncOperLogService.saveSysOperLog(sysOperLog);

        // 返回执行结果
        return proceed;
    }
}
